home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / intrlib1.zip / MOUSEDRV.C < prev    next >
C/C++ Source or Header  |  1992-03-10  |  14KB  |  379 lines

  1. /******************************************************************************
  2. * Iteraction library - windows.                              *
  3. *                                          *
  4. *                    Written by Gershon Elber,  Oct. 1990  *
  5. *******************************************************************************
  6. * W A R N I N G : This module assumes mouse driver was installed using          *
  7. * one of the following program: mouse.com or mouse.sys.                  *
  8. *                                          *
  9. * This module can be compiled in any model (tiny..huge)                  *
  10. *                                          *
  11. * The following routines are available:                          *
  12. * 1. MouseSetResolution(int Resolution) - set mouse rosolution.              *
  13. * 2. MouseDetect() - returns TRUE if mouse detected in system.              *
  14. * 3. MouseInit() - must be called first before any other call.              *
  15. * 4. MouseShowCorsur() - show mouse cursor.                      *
  16. * 5. MouseHideCorsur() - hide mouse cursor.                      *
  17. * 6. MouseSetPosition() - set mouse XY position.                  *
  18. * 7. MouseQueryBuffer() - returns event ring buffer status.              *
  19. * 8. MouseQueryDataBuffer() - returns event ring buffer data status.          *
  20. * 9. MouseGetBuffer() - returns next event from ring buffer.              *
  21. * 10.MouseFlushBuffer() - clear all data currently in buffer.              *
  22. * 11.MouseClose() - must be called last before application program dies.      *
  23. *                                          *
  24. * Note that as the mouse driver is used asyncronically (i.e. interrupts)      *
  25. * fail to call MouseInit() at the begining or even worse, call              *
  26. * MouseClose() in the end is an invitation for total system disaster!          *
  27. *                                          *
  28. * Written by:  Gershon Elber            IBM PC Ver 0.1,    Sep. 1988     *
  29. *                                          *
  30. * Ver 0.2 - No interrupt vector is used (MouseHandler is called directly).    *
  31. ******************************************************************************/
  32.  
  33. /* #define  DEBUG             * Uncomment it for simple test routine. */
  34.  
  35. #include <dos.h>
  36. #include <stdio.h>
  37. #include "MouseDrv.h"
  38.  
  39. #ifdef   DEBUG
  40. #include <conio.h>
  41. #endif   DEBUG
  42.  
  43. #define ABS(x)    ((x) > 0 ? (x) : (-(x)))
  44.  
  45. /* Two external integers defined Mouse Range (start from 0): */
  46. int MSMouseXmax = 1000,
  47.     MSMouseYmax = 1000;
  48.  
  49. static int BufferHead, BufferTail, BufferFull,     /* Implement ring buffer. */
  50.        BufferOverRun,          /* Over run error in mouse buffer. */
  51.        MouseBuffer[BUFFER_SIZE][2],          /* Mouse event to save. */
  52.        WasMouseSetUp = FALSE,    /* TRUE - mouse successfully installed. */
  53.        SkipMouseEvents = 1;           /* Number of move events to skip + 1. */
  54. static struct SREGS SRegs;
  55.  
  56. static void MouseSysCall(int Func, int *m2, int *m3, int *m4);
  57.  
  58. /**************************************************************************
  59. * Static routine that is used to save DS register, so it can be restore   *
  60. * when the Mouse Handler is invoked. This routine is used only to      *
  61. * allocate space in the code segment for one integer (DS), and is never   *
  62. * been called. If you have better solution how to restore DS let me know! *
  63. **************************************************************************/
  64. static void far SaveDSOnThisRoutine(void)
  65. {
  66.     SRegs.ds = _DS;           /* Looks like something useful - its NOT! */
  67. }
  68.  
  69. /**************************************************************************
  70. * Set resolution for mouse.                              *
  71. **************************************************************************/
  72. void MouseSetResolution(int Resolution)
  73. {
  74.     MSMouseXmax = MSMouseYmax = Resolution;
  75. }
  76.  
  77. /**************************************************************************
  78. * Mouse detect routine. Does three step test:                  *
  79. * 1. Test if there is none NULL vector in vector interrupt 0x33 which     *
  80. *    should hold the mouse driver.                      *
  81. * 2. Test if that pointer is pointing on IRET instruction or not.      *
  82. * 3. Test if the mouse is connected by calling to the mouse driver -      *
  83. *    sys call 0x00.                              *
  84. **************************************************************************/
  85. int MouseDetect(void)
  86. {
  87.     unsigned char far *Ptr;
  88.     union REGS Regs;
  89.  
  90.     /* Look if anything is installed in the mouse interrupt vector: */
  91.     if (((Ptr = (unsigned char far *) getvect(0x33)) == NULL) ||
  92.     (*Ptr == 0xcf /* IRET */)) return FALSE;
  93.  
  94.     Regs.x.ax = 0;              /* Select reset and test function. */
  95.      /* interrupt 51 decimal is used by mouse device driver itself: */
  96.     int86x(0x33, &Regs, &Regs, &SRegs);
  97.  
  98.     return (Regs.x.ax);
  99. }
  100.  
  101. /**************************************************************************
  102. * This is the mouse handler itself: called from mouse driver on events.   *
  103. * The x, y coordinates are saved as two integers in the buffer as follows:*
  104. * X is positive if Left Button is pressed, Negative otherwise.          *
  105. * Y is positive if Right Button is pressed, Negative otherwise.          *
  106. * Note 1 is added to X, Y to make them none zero...              *
  107. * Also note DS must be restore before data (event buffer) is accessed.    *
  108. **************************************************************************/
  109. static void far MouseHandler(void)
  110. {
  111.     static int Skip = 0;
  112.     int far *RestoreDS = (int far *) SaveDSOnThisRoutine;
  113.     int Buttons = _BX, X = _CX, Y = _DX, SaveDS = _DS;
  114.  
  115.     _DS = *RestoreDS;
  116.  
  117.     if (Skip++ < SkipMouseEvents && !Buttons) return;
  118.     Skip = 0;
  119.  
  120.     if (BufferFull)
  121.     BufferOverRun = TRUE;                 /* Buffer overflow. */
  122.     else {
  123.     if (Buttons > 0x03) Buttons = 0x03;
  124.     MouseBuffer[BufferHead][0] = (Buttons & 0x01 ? X+1 : -X-1);
  125.     MouseBuffer[BufferHead++][1] = (Buttons & 0x02 ? Y+1 : -Y-1);
  126.     if (BufferHead == BUFFER_SIZE) BufferHead = 0;
  127.     if (BufferHead == BufferTail) BufferFull = TRUE;
  128.     }
  129.     _DS = SaveDS;
  130. }
  131.  
  132. /**************************************************************************
  133. * See all description on all functions available (0-16, 19) on page 54 in *
  134. * Microsoft Mouse manual.                          *
  135. **************************************************************************/
  136. static void MouseSysCall(int Func, int *m2, int *m3, int *m4)
  137. {
  138.     union REGS Regs;
  139.  
  140.     Regs.x.ax = Func;               /* Select the requested function. */
  141.     Regs.x.bx = *m2;
  142.     Regs.x.cx = *m3;
  143.     Regs.x.dx = *m4;
  144.  
  145.      /* interrupt 51 decimal is used by mouse device driver itself: */
  146.     int86x(0x33, &Regs, &Regs, &SRegs);
  147.  
  148.     *m2 = Regs.x.bx;
  149.     *m3 = Regs.x.cx;
  150.     *m4 = Regs.x.dx;
  151. }
  152.  
  153. /**************************************************************************
  154. * Mouse Initialization: return NULL if succesful, else error msg string.  *
  155. **************************************************************************/
  156. char *MouseInit(int Sensitivity)
  157. {
  158.     int far *SaveDS;
  159.     int m2, m3, m4;
  160.  
  161.     if (WasMouseSetUp)
  162.     return "MouseInit: Mouse already initialized, ignored.";
  163.     if (MSMouseXmax == 0 || MSMouseYmax == 0)
  164.     return "MouseInit: Mouse range was not initialized by graphic driver.";
  165.  
  166.     SkipMouseEvents = 0;          /* Takes too much time to redraw cursor... */
  167.  
  168.     SRegs.ds = _DS; /* In case the communication with the driver needs that. */
  169.     SaveDS = (int far *) SaveDSOnThisRoutine;
  170.     *SaveDS = _DS;
  171.  
  172.     BufferHead = BufferTail = 0;           /* Reset the Buffer pointers. */
  173.     BufferFull = BufferOverRun = FALSE;
  174.  
  175.     MouseSysCall(0, &m2, &m3, &m4);               /* Install Mouse. */
  176.  
  177.     m3 = 0;
  178.     m4 = MSMouseXmax;
  179.     MouseSysCall(7, &m2, &m3, &m4);            /* Set Column Range. */
  180.     m3 = 0;
  181.     m4 = MSMouseYmax;
  182.     MouseSysCall(8, &m2, &m3, &m4);               /* Set Row Range. */
  183.     m3 = Sensitivity;
  184.     m4 = Sensitivity;
  185.     MouseSysCall(15, &m2, &m3, &m4);        /* Set Mickeys Per 8 pixels. */
  186.  
  187.     m3 = 0x2b;/* Set bits 0, 1, 3, 5 - intrpt on mouse move & button pressed.*/
  188.     m4 = FP_OFF(MouseHandler);
  189.     SRegs.es = FP_SEG(MouseHandler);
  190.     MouseSysCall(12, &m2, &m3, &m4);     /* Link the MouseHandler() routine. */
  191.  
  192.     WasMouseSetUp = TRUE;
  193.  
  194.     return NULL;
  195. }
  196.  
  197. /**************************************************************************
  198. * Mouse Closing:                              *
  199. **************************************************************************/
  200. void MouseClose(void)
  201. {
  202.     int m2, m3, m4;
  203.  
  204.     if (!WasMouseSetUp) return;                 /* Install mouse first! */
  205.  
  206.     m3 = 0x00;                    /* No interrupts any more... */
  207.     MouseSysCall(12, &m2, &m3, &m4);
  208.  
  209.     WasMouseSetUp = FALSE;
  210. }
  211.  
  212. /**************************************************************************
  213. * Routine returns TRUE if buffer is not empty.                  *
  214. **************************************************************************/
  215. int MouseQueryBuffer(void)
  216. {
  217.     return (BufferFull || BufferHead != BufferTail);
  218. }
  219.  
  220. /**************************************************************************
  221. * Routine to return Mouse buffer status:                  *
  222. * Returns TRUE if buffer is not empty. In addition sets X, Y, Buttons to  *
  223. * the end of buffer without modifying the buffer, and set OverRunError.      *
  224. **************************************************************************/
  225. int MouseQueryDataBuffer(int *X, int *Y, int *Buttons, int *OverRunError)
  226. {
  227.     if (BufferFull || BufferHead != BufferTail) {
  228.     *X = ABS(MouseBuffer[BufferTail][0]) - 1;
  229.     *Y = ABS(MouseBuffer[BufferTail][1]) - 1;
  230.     *Buttons = (MouseBuffer[BufferTail][0] > 0 ? 0x01 : 0x00) +
  231.            (MouseBuffer[BufferTail][1] > 0 ? 0x02 : 0x00);
  232.     *OverRunError = BufferOverRun;
  233.     return TRUE;
  234.     }
  235.     else
  236.     return FALSE;
  237. }
  238.  
  239. /**************************************************************************
  240. * Routine to get one event from buffer. waits for one if buffer empty.    *
  241. * Returns OverRun status - TRUE if over run occurs. In addition sets      *
  242. * X, Y, Buttons to the end of buffer, and increment.              *
  243. **************************************************************************/
  244. int MouseGetBuffer(int *X, int *Y, int *Buttons)
  245. {
  246.     /* Wait for event if buffer is empty: */
  247.     while (!(BufferFull || BufferHead != BufferTail));
  248.  
  249.     *X = ABS(MouseBuffer[BufferTail][0]) - 1;
  250.     *Y = ABS(MouseBuffer[BufferTail][1]) - 1;
  251.     *Buttons = (MouseBuffer[BufferTail][0] > 0 ? 0x01 : 0x00) +
  252.            (MouseBuffer[BufferTail][1] > 0 ? 0x02 : 0x00);
  253.  
  254.     disable();                           /* No interrupts now! */
  255.     if (BufferHead == BufferTail) BufferFull = FALSE;
  256.     if (++BufferTail == BUFFER_SIZE) BufferTail = 0;
  257.     enable();                         /* interrupts o.k. now. */
  258.  
  259.     return BufferOverRun;
  260. }
  261.  
  262. /**************************************************************************
  263. * Routine to flush and clear all the mouse event buffer.          *
  264. **************************************************************************/
  265. void MouseFlushBuffer(void)
  266. {
  267.     disable();                           /* No interrupts now! */
  268.     BufferHead = BufferTail;
  269.     BufferFull = BufferOverRun = FALSE;
  270.     enable();                         /* interrupts o.k. now. */
  271. }
  272.  
  273. /**************************************************************************
  274. * Mouse Show Cursor:                              *
  275. **************************************************************************/
  276. void MouseShowCursor(void)
  277. {
  278.     int m2, x, y;
  279.  
  280.     MouseSysCall(1, &m2, &x, &y);                 /* Show cursor. */
  281. }
  282.  
  283. /**************************************************************************
  284. * Mouse Hide Cursor:                              *
  285. **************************************************************************/
  286. void MouseHideCursor(void)
  287. {
  288.     int m2, x, y;
  289.  
  290.     MouseSysCall(2, &m2, &x, &y);                 /* Hide cursor. */
  291. }
  292.  
  293. /**************************************************************************
  294. * Mouse Set Position:                              *
  295. **************************************************************************/
  296. void MouseSetPosition(int X, int Y)
  297. {
  298.     int dummy;
  299.  
  300.     MouseSysCall(4, &dummy, &X, &Y);                /* Set position. */
  301. }
  302.  
  303. #ifdef DEBUG
  304.  
  305. /**************************************************************************
  306. * Routine to make some sound with given Frequency, Time milliseconds:      *
  307. **************************************************************************/
  308. void GGTone(int Frequency, int Duration)
  309. {
  310.     sound(Frequency);
  311.     delay(Duration);
  312.     nosound();
  313. }
  314.  
  315. /**************************************************************************
  316. * Exit routine.                                  *
  317. **************************************************************************/
  318. void MyExit(int ErrCode)
  319. {
  320.     exit(ErrCode);
  321. }
  322.  
  323. /**************************************************************************
  324. * Simple test routine:                              *
  325. **************************************************************************/
  326. void main(void)
  327. {
  328.     int X, Y, Buttons;
  329.  
  330.     if (!MouseDetect()) {
  331.     fprintf(stderr, "No mouse was detected, can'nt continue\n");
  332.     MyExit(1);
  333.     }
  334.  
  335.     MSMouseXmax = 1000;
  336.     MSMouseYmax = 1000;
  337.  
  338.     clrscr();                            /* Clear screen. */
  339.     MouseInit(10);                       /* Install Mouse. */
  340.     MouseShowCursor();
  341.  
  342.     gotoxy (2, 10);
  343.     printf("Press any button, or move mouse to get events. Press both buttons to exit.");
  344.  
  345.     do {
  346.     while (!kbhit() && !MouseQueryBuffer());
  347.     if (kbhit()) break;
  348.  
  349.     if (MouseGetBuffer (&X, &Y, &Buttons)) {
  350.         gotoxy(33, 15);
  351.         printf("Over Run Error");
  352.         MouseFlushBuffer();
  353.         sleep(1);
  354.         gotoxy(33, 15);
  355.         printf("              ");
  356.     }
  357.  
  358.     gotoxy(20, 5);
  359.     printf("Head = %3d, Tail = %3d, Full = %3d\n",
  360.                 BufferHead, BufferTail, BufferFull);
  361.  
  362.     gotoxy(16, 1);
  363.         if ((Buttons & 0x01) != 0)
  364.         printf(" Left ");
  365.     else if ((Buttons & 0x02) != 0)
  366.         printf("Right ");
  367.     else
  368.         printf("   No ");
  369.         printf("Button was pushed at X=%-3d  Y=%-3d", X, Y);
  370.     }
  371.     while ((Buttons & 0x03) != 0x03);        /* Both buttons were pushed. */
  372.  
  373.     MouseHideCursor();
  374.     MouseClose();
  375.     clrscr();                            /* Clear screen. */
  376. }
  377.  
  378. #endif  DEBUG
  379.